#include "WanderInRegion.h"
#include "Animation.h"
#include "WIRidle.h"
#include "WIRwalking.h"
#include "Logger.h"
#include "Exception.h"

using namespace game_engine;
using namespace game_engine::components;
using namespace game_engine::library;
using namespace game_engine::utils;

///////////////////////////////////////////////////////////////////////////////
// Constructors and Destructors
///////////////////////////////////////////////////////////////////////////////

WanderInRegion::WanderInRegion(void)
    : Behaviour(), region(), idleAnimationId(), walkSpeed(0.0f), 
    maxWaitingTime(0.0f), _isWalking(false)//, idleState(NULL), walkingState(NULL)
{
    type = "WanderInRegion";
    walkAnimationId.clear();
}

WanderInRegion::WanderInRegion(GameObject *obj, const Rect &reg)
    : Behaviour(obj), region(reg), idleAnimationId(), walkSpeed(0.0f), 
    maxWaitingTime(0.0f), _isWalking(false)//, idleState(NULL), walkingState(NULL)
{
    type = "WanderInRegion";
    walkAnimationId.clear();
}

WanderInRegion::~WanderInRegion(void)
{
    //delete idleState;
    //delete walkingState;
}

///////////////////////////////////////////////////////////////////////////////
// Other public methods
///////////////////////////////////////////////////////////////////////////////

void WanderInRegion::initialize(void) throw(...)
{
    // Create the states of this behaviour
    //idleState = new WIRidle(this, maxWaitingTime);
    //walkingState = new WIRwalking(this);
    //setCurrentState(idleState);
    setCurrentState(new WIRidle(this, maxWaitingTime));
    _isWalking = false;

    // Check that all not NULL animations are defined into an
    // Animation component of the same object
    Animation *anim = dynamic_cast<Animation*> (getComponent(object, "Animation"));
    vector<string> list;
    list.push_back(idleAnimationId);

    map<Direction,string>::const_iterator j;
    for (j=walkAnimationId.begin(); j!=walkAnimationId.end(); j++)
    {
        list.push_back((*j).second);
    }
    
    vector<string>::iterator it;
    for (it=list.begin(); it<list.end(); it++)
    {
        if ((!(*it).empty()) && (!anim->sequenceExists(*it)))
        {
            string err("Animation ");
            err.append(*it);
            err.append(" not defined in Animation component");
            Logger::ERR(GAMEENGINE_LOG, err);
            throw NoSuchElementException(err);
        }
    }

    // Base class initialization
    Behaviour::initialize();
}

void WanderInRegion::forceDestinationReached(void) throw(...)
{
    if (_isWalking)
    {
        WIRwalking *state = dynamic_cast<WIRwalking*> (currentState);
        state->forceDestinationReached();
    }
}

///////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////

const Rect& WanderInRegion::getRegion(void) const
{
    return region;
}

const string& WanderInRegion::getIdleAnimationId(void) const
{
    return idleAnimationId;
}

const string WanderInRegion::getWalkAnimationId(const Direction direction) const
{
    // Check for existance
    map<Direction,string>::const_iterator it;
    it = walkAnimationId.find(direction);
    if (it == walkAnimationId.end())
    {
        return string();
    }
    return (*it).second;
}

const FLOAT32 WanderInRegion::getWalkSpeed(void) const
{
    return walkSpeed;
}

const FLOAT32 WanderInRegion::getMaxWaitingTime(void) const
{
    return maxWaitingTime;
}

const BOOL WanderInRegion::isWalking(void) const
{
    return _isWalking;
}

///////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////

void WanderInRegion::setRegion(const Rect &reg)
{
    region = reg;
}

void WanderInRegion::setIdleAnimationId(const string &animId)
{
    idleAnimationId = animId;
}

void WanderInRegion::setWalkAnimationId(const Direction direction, 
                                        const string &animId)
{
    walkAnimationId[direction] = animId;
}

void WanderInRegion::setWalkSpeed(const FLOAT32 speed)
{
    walkSpeed = speed;
}

void WanderInRegion::setMaxWaitingTime(const FLOAT32 time)
{
    maxWaitingTime = time;
}

void WanderInRegion::setIsWalking(const BOOL isWalking)
{
    _isWalking = isWalking;
}
